package com.icinfo.cloud.provider.punish.common.datareport.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.icinfo.cloud.common.core.config.RedisRepository;
import com.icinfo.cloud.provider.common.constant.Constant;
import com.icinfo.cloud.provider.common.utils.SharedHttpUtil;
import com.icinfo.cloud.provider.common.utils.SharedMd5Util;
import com.icinfo.cloud.provider.punish.common.datareport.service.ICaseDataReportSecretReceiveService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 描述：案件数据上报密钥获取接口实现类
 *
 * @author xiangyuyu
 * @date 2022/3/30 14:24
 */
@Service
@Slf4j
public class CaseDataReportSecretReceiveServiceImpl implements ICaseDataReportSecretReceiveService {
    @Value("${dataReport.app.key}")
    private String appKey;
    @Value("${dataReport.app.secret}")
    private String requestSecret;
    @Value("${dataReport.receiveSecretUrl}")
    private String receiveSecretUrl;
    @Value("${dataReport.receiveSecretSecUrl}")
    private String receiveSecretSecUrl;
    private final SharedHttpUtil httpUtil = SharedHttpUtil.getInstance();
    @Resource
    private RedisRepository redisRepository;
    private static String KEY_ID = "punish-request-secret";
    
    /**
     * 描述：获取密钥
     *
     * @return String 密钥
     * @author xiangyuyu
     * @date 2022-03-30 15:45
     */
    @Override
    public String getSecret() {
        LocalDateTime startTime = LocalDateTime.now();
        log.info("getSecret start...startTime:{}", startTime);
        String secret = "";
        //刷新密钥
        String refreshSecret = redisRepository.get("punish-refreshSecret");
        Object refreshSecretEndTimeObj = redisRepository.get("punish-refreshSecretEndTime");
        Object requestSecretEndTimeObj = redisRepository.get("punish-requestSecretEndTime");
        log.info("refreshSecret:{},refreshSecretEndTimeObj:{},requestSecretEndTimeObj:{}", refreshSecret, refreshSecretEndTimeObj, requestSecretEndTimeObj);
        //请求密钥有效期截止时间
        Date requestSecretEndTime = null;
        //刷新密钥有效期截止时间
        Date refreshSecretEndTime = null;
        Date now = new Date();
        //5分钟
        long tmpTime = 300000L;
        //避免刚好15分钟缓存拿到有效，请求过去却失效的临界点

        now = new Date(now .getTime() + tmpTime);
        String urls = receiveSecretUrl;
        if (!ObjectUtils.isEmpty(requestSecretEndTimeObj)) {
            if (requestSecretEndTimeObj instanceof Date) {
                requestSecretEndTime = (Date) requestSecretEndTimeObj;
            } else if (requestSecretEndTimeObj instanceof String) {
                requestSecretEndTime = new Date(Long.parseLong(requestSecretEndTimeObj.toString()));
            } else if (requestSecretEndTimeObj instanceof Long) {
                requestSecretEndTime = new Date(Long.parseLong(requestSecretEndTimeObj.toString()));
            }
            log.info("getSecret-requestSecretEndTime:{}", requestSecretEndTime);
            if (!ObjectUtils.isEmpty(requestSecretEndTime) && now.after(requestSecretEndTime)) {
                //请求密钥过期（有效期15分钟）
                if (!ObjectUtils.isEmpty(refreshSecretEndTimeObj)) {
                    if (refreshSecretEndTimeObj instanceof Date) {
                        refreshSecretEndTime = (Date) refreshSecretEndTimeObj;
                    } else if (refreshSecretEndTimeObj instanceof String) {
                        refreshSecretEndTime = new Date(Long.parseLong(refreshSecretEndTimeObj.toString()));
                    } else if (refreshSecretEndTimeObj instanceof Long) {
                        refreshSecretEndTime = new Date(Long.parseLong(refreshSecretEndTimeObj.toString()));
                    }
                    log.info("getSecret-refreshSecretEndTime:{}", refreshSecretEndTime);
                    //1小时
                    tmpTime = 3600000L;
                    //避免刚好48小时缓存拿到有效，请求过去却失效的临界点（在上面+5分钟基础上+1小时）
                    now = new Date(now .getTime() + tmpTime);
                    if (!ObjectUtils.isEmpty(refreshSecretEndTime) && now.after(refreshSecretEndTime)) {
                        //刷新密钥过期（有效期48小时）（使用App密钥）
                        urls = receiveSecretUrl;
                        refreshSecret = requestSecret;
                        log.info("刷新密钥过期,urls:{},refreshSecret:{}", urls, refreshSecret);
                    } else if (!ObjectUtils.isEmpty(refreshSecretEndTime) && now.before(refreshSecretEndTime)) {
                        urls = receiveSecretSecUrl;
                        log.info("刷新密钥未过期,urls:{},refreshSecret:{}", urls,refreshSecret);
                    } else {
                        //requestSecretEndTime 为空
                        urls = receiveSecretUrl;
                        refreshSecret = requestSecret;
                    }
                } else {
                    //刷新密钥过期或无刷新密钥（使用App密钥）
                    urls = receiveSecretUrl;
                    refreshSecret = requestSecret;
                    log.info("刷新密钥过期或无刷新密钥（使用App密钥）urls:{},refreshSecret:{}", urls, refreshSecret);
                }
            } else if(!ObjectUtils.isEmpty(requestSecretEndTime) && now.before(requestSecretEndTime)){
                secret = getCacheSecret(KEY_ID);
                log.info("请求密钥在有效期内，直接返回secret:{}", secret);
                return secret;
            } else {
                //刷新密钥过期或无刷新密钥（使用App密钥）
                urls = receiveSecretUrl;
                refreshSecret = requestSecret;
                log.info("刷新密钥过期或无刷新密钥（使用App密钥）urls:{},refreshSecret:{}", urls, refreshSecret);
            }
        } else {
            //刷新密钥过期或无刷新密钥（使用App密钥）
            urls = receiveSecretUrl;
            refreshSecret = requestSecret;
            log.info("刷新密钥过期或无刷新密钥（使用App密钥）urls:{},refreshSecret:{}", urls, refreshSecret);
        }
        long time = System.currentTimeMillis();
        String sign = SharedMd5Util.hash(appKey + refreshSecret + time);
        Map<String, String> params = new HashMap<>(8);
        params.put("appKey", appKey);
        params.put("sign", sign);
        params.put("requestTime", time + "");
        log.info("getSecret before request param:{}", params);
        String result = httpUtil.sendHttpPost(urls, params);
        log.info("getSecret after request result:{}", result);
        if (!ObjectUtils.isEmpty(result)) {
            JSONObject resultJO = JSONObject.parseObject(result);
            if (!ObjectUtils.isEmpty(resultJO)) {
                JSONObject data = resultJO.getJSONObject(Constant.STRING_DATAS_LOWER);
                if (ObjectUtils.isEmpty(data)) {
                    log.error("getSecret 相应data为null,msg:{}", resultJO.getString(Constant.STRING_MSG_LOWER));
                    urls = receiveSecretUrl;
                    refreshSecret = requestSecret;
                    time = System.currentTimeMillis();
                    sign = SharedMd5Util.hash(appKey + refreshSecret + time);
                    params = new HashMap<>(8);
                    params.put("appKey", appKey);
                    params.put("sign", sign);
                    params.put("requestTime", time + "");
                    log.info("getSecret before request-re param:{}", params);
                    result = httpUtil.sendHttpPost(urls, params);
                    log.info("getSecret after request-re result:{}", result);
                    if (!ObjectUtils.isEmpty(result)) {
                        resultJO = JSONObject.parseObject(result);
                        if (!ObjectUtils.isEmpty(resultJO)) {
                            data = resultJO.getJSONObject(Constant.STRING_DATAS_LOWER);
                            if (ObjectUtils.isEmpty(data)) {
                                log.error("getSecret-re 相应data为null,msg:{}", resultJO.getString(Constant.STRING_MSG_LOWER));
                            } else {
                                secret = data.getString("requestSecret");
                                refreshSecret = data.getString("refreshSecret");
                                requestSecretEndTimeObj = data.get("requestSecretEndTime");
                                refreshSecretEndTimeObj = data.get("refreshSecretEndTime");
                                //cache key_id
                                cacheSecret(KEY_ID, secret);
                                cacheSecret("punish-refreshSecret", refreshSecret);
                                if (!ObjectUtils.isEmpty(requestSecretEndTimeObj)) {
                                    cacheSecret("punish-requestSecretEndTime", requestSecretEndTimeObj.toString());
                                }
                                if (!ObjectUtils.isEmpty(refreshSecretEndTimeObj)) {
                                    cacheSecret("punish-refreshSecretEndTime", refreshSecretEndTimeObj.toString());
                                }
                            }
                        } else {
                            log.error("re-获取密钥时出现异常");
                        }
                    } else {
                        log.error("getSecret-re urls:{},result:{}", urls, result);
                    }
                } else {
                    secret = data.getString("requestSecret");
                    refreshSecret = data.getString("refreshSecret");
                    requestSecretEndTimeObj = data.get("requestSecretEndTime");
                    refreshSecretEndTimeObj = data.get("refreshSecretEndTime");
                    //cache key_id
                    cacheSecret(KEY_ID, secret);
                    cacheSecret("punish-refreshSecret", refreshSecret);
                    if (!ObjectUtils.isEmpty(requestSecretEndTimeObj)) {
                        cacheSecret("punish-requestSecretEndTime", requestSecretEndTimeObj.toString());
                    }
                    if (!ObjectUtils.isEmpty(refreshSecretEndTimeObj)) {
                        cacheSecret("punish-refreshSecretEndTime", refreshSecretEndTimeObj.toString());
                    }
                }
            } else {
                log.error("获取密钥时出现异常");
            }
        } else {
            log.error("getSecret urls:{},result:{}", urls, result);
        }
        LocalDateTime endTime = LocalDateTime.now();
        log.info("getSecret end ! endTime:{}", endTime);
        return secret;
    }

    /**
     * 描述：获取缓存密钥
     *
     * @param keyId 查询密钥id
     * @return String 缓存密钥
     * @author xiangyuyu
     * @date 2022-03-30 15:16
     */
    public String getCacheSecret(String keyId) {
        String secret = redisRepository.get(keyId);
        return secret;
    }

    /**
     * 描述：缓存密钥
     *
     * @param keyId  查询密钥id
     * @param secret 密钥
     * @return 缓存错误信息（空代表缓存成功）
     * @author xiangyuyu
     * @date 2022-03-30 15:03
     */
    public String cacheSecret(String keyId, String secret) {
        String errorMsg = "";
        redisRepository.set(keyId, secret);
        //暂定有效期2小时
        //redisRepository.setExpire(keyId, secret, 2*60*60);
        return errorMsg;
    }
}
